招银网络一面,抗揍40分钟,过啦!
大家好,我是二哥呀。
招商银行网络科技也开始约面了,有牛友一面面了 40 分钟,面试体验很好,说答不上来会给讲解。
我看了一面的内容,确实比互联网大厂友好太多,不是那种纯粹的八股,反而带有一些很有深度的思考。
招银网络科技也是很多小伙伴心仪的对象,因为银行一般比较稳定,同时招银的研发也是比较贴合互联网公司,不至于进去后把技术这块丢了。
虽然有加班,但强度不算是特别大,能有一个比较好的平衡。那今天我们就以 Java 面试指南中收录的同学 9 招银网络一面为例,来看看招银的面试官都喜欢问哪些问题,好做到心中有数,面试不慌。
1、《30 天速通 Java.pdf》下载 2、三分恶面渣逆袭在线版:https://javabetter.cn/sidebar/sanfene/nixi.html
招银网络科技同学 9 一面面经
Java堆内存和栈内存的区别
堆属于线程共享的内存区域,几乎所有的对象都在堆上分配,生命周期不由单个方法调用所决定,可以在方法调用结束后继续存在,直到不再被任何变量引用,然后被垃圾收集器回收。
栈属于线程私有的内存区域,主要存储局部变量、方法参数、对象引用等,通常随着方法调用的结束而自动释放,不需要垃圾收集器处理。
Java设计模式中的开闭原则,里氏替换了解?
开闭原则(Open-Closed Principle, OCP),指软件实体应该对扩展开放,对修改关闭。这意味着一个类应该通过扩展来实现新的功能,而不是通过修改已有的代码来实现。
举个例子,在不遵守开闭原则的情况下,有一个需要处理不同形状的绘图功能类。
class ShapeDrawer {
public void draw(Shape shape) {
if (shape instanceof Circle) {
drawCircle((Circle) shape);
} else if (shape instanceof Rectangle) {
drawRectangle((Rectangle) shape);
}
}
private void drawCircle(Circle circle) {
// 画圆形
}
private void drawRectangle(Rectangle rectangle) {
// 画矩形
}
}
每增加一种形状,就需要修改一次 draw 方法,这违反了开闭原则。正确的做法是通过继承和多态来实现新的形状类,然后在 ShapeDrawer 中添加新的 draw 方法。
// 抽象的 Shape 类
abstract class Shape {
public abstract void draw();
}
// 具体的 Circle 类
class Circle extends Shape {
@Override
public void draw() {
// 画圆形
}
}
// 具体的 Rectangle 类
class Rectangle extends Shape {
@Override
public void draw() {
// 画矩形
}
}
// 使用开闭原则的 ShapeDrawer 类
class ShapeDrawer {
public void draw(Shape shape) {
shape.draw(); // 调用多态的 draw 方法
}
}
里氏代换原则也被称为李氏替换原则(Liskov Substitution Principle, LSP),其规定任何父类可以出现的地方,子类也一定可以出现。
LSP 是继承复用的基石,只有当子类可以替换掉父类,并且单位功能不受到影响时,父类才能真正被复用,而子类也能够在父类的基础上增加新的行为。
这意味着子类在扩展父类时,不应改变父类原有的行为。例如,如果有一个方法接受一个父类对象作为参数,那么传入该方法的任何子类对象也应该能正常工作。
class Bird {
void fly() {
System.out.println("鸟正在飞");
}
}
class Duck extends Bird {
@Override
void fly() {
System.out.println("鸭子正在飞");
}
}
class Ostrich extends Bird {
// Ostrich违反了LSP,因为鸵鸟不会飞,但却继承了会飞的鸟类
@Override
void fly() {
throw new UnsupportedOperationException("鸵鸟不会飞");
}
}
在这个例子中,Ostrich(鸵鸟)类违反了 LSP 原则,因为它改变了父类 Bird 的行为(即飞行)。
说一说常用的设计模式
单例模式、策略模式和工厂模式。
在需要控制资源访问,如配置管理、连接池管理时经常使用单例模式。它确保了全局只有一个实例,并提供了一个全局访问点。
在有多种算法或策略可以切换使用的情况下,我会使用策略模式。像技术派实战项目中,我就使用策略模式对接了讯飞星火、OpenAI、智谱 AI 等多家大模型,实现了一个可以自由切换大模型基座的智能助手服务。
策略模式的好处是,不用在代码中写 if/else 判断,而是将不同的 AI 服务封装成不同的策略类,通过工厂模式创建不同的 AI 服务实例,从而实现 AI 服务的动态切换。
后面想添加新的 AI 服务,只需要增加一个新的策略类,不需要修改原有代码,这样就提高了代码的可扩展性。
Mysql联合索引的设计原则
在使用联合索引时,应当遵守最左前缀原则,或者叫最左匹配原则(最左前缀匹配原则)。
它指的是在使用联合索引时,查询条件从索引的最左列开始并且不跳过中间的列。
如果一个复合索引包含(col1, col2, col3)
,那么它可以支持 col1
、col1,col2
和 col1, col2, col3
的查询优化,但不支持只有 col2 或 col3 的查询。
也就说,在进行查询时,如果没有遵循最左前缀,那么联合索引可能不会被利用,导致查询效率降低。
select for update 加锁有什么需要注意的
如果查询条件使用了索引(特别是主键索引或唯一索引),SELECT FOR UPDATE 会锁定特定的行,即行级锁,这样锁的粒度较小,不会影响未涉及的行或其他并发操作。
但如果查询条件未使用索引,SELECT FOR UPDATE 可能锁定整个表或大量的行,因为查询需要执行全表扫描。
假设有一张名为 orders 的表,包含以下数据:
CREATE TABLE orders (
id INT PRIMARY KEY,
order_no VARCHAR(255),
amount DECIMAL(10,2),
status VARCHAR(50),
INDEX (order_no) -- order_no 上有索引
);
表中的数据是这样的:
id | order_no | amount | status |
---|---|---|---|
1 | 10001 | 50.00 | pending |
2 | 10002 | 75.00 | pending |
3 | 10003 | 100.00 | pending |
4 | 10004 | 150.00 | completed |
5 | 10005 | 200.00 | pending |
如果我们通过主键索引执行 SELECT FOR UPDATE,只会锁定特定的行:
START TRANSACTION;
SELECT * FROM orders WHERE id = 1 FOR UPDATE;
-- 对 id=1 的行进行操作
COMMIT;
由于 id 是主键,所以只会锁定 id=1
这行,不会影响其他行的操作。其他事务依然可以对 id = 2, 3, 4, 5 等行执行更新操作,因为它们没有被锁定。
如果使用 order_no 索引执行 SELECT FOR UPDATE,也只会锁定特定的行:
START TRANSACTION;
SELECT * FROM orders WHERE order_no = '10001' FOR UPDATE;
-- 对 order_no=10001 的行进行操作
COMMIT;
因为 order_no 上有索引,所以只会锁定 order_no=10001
这行,不会影响其他行的操作。
但如果查询 status='pending'
,而 status 上没有索引:
START TRANSACTION;
SELECT * FROM orders WHERE status = 'pending' FOR UPDATE;
-- 对 status=pending 的行进行操作
COMMIT;
查询需要执行全表扫描。在这种情况下,SELECT FOR UPDATE 可能会锁定表中所有符合条件的记录,甚至是整个表,因为 MySQL 需要检查每一行的 status。
这会影响表中的大部分记录,其他事务将无法修改这些记录,直到当前事务结束。
如何保证交易,订单等不会重复处理
在小规模系统中,数据库锁和唯一索引通常就足够保证交易订单不会被重复处理了;但在高并发的分布式系统中,还需要配合分布式锁来进一步保证。
数据量在500w的表,如何实现快速的全表模糊匹配
首先要使用合适的索引,LIKE 'pattern%' 可以使用普通索引,而 LIKE '%pattern%' 可以考虑 MySQL 的 FULLTEXT 索引;如果还不满足,可以使用 Elasticsearch。
内容来源
星球嘉宾三分恶的面渣逆袭:https://javabetter.cn/sidebar/sanfene/nixi.html 二哥的 Java 进阶之路(GitHub 已有 12000+star):https://javabetter.cn
ending
一个人可以走得很快,但一群人才能走得更远。二哥的编程星球已经有 6100 多名球友加入了,如果你也需要一个良好的学习环境,戳链接 🔗 加入我们吧。这是一个编程学习指南 + Java 项目实战 + LeetCode 刷题的私密圈子,你可以阅读星球专栏、向二哥提问、帮你制定学习计划、和球友一起打卡成长。
两个置顶帖「球友必看」和「知识图谱」里已经沉淀了非常多优质的学习资源,相信能帮助你走的更快、更稳、更远。
欢迎点击左下角阅读原文了解二哥的编程星球,这可能是你学习求职路上最有含金量的一次点击。
最后,把二哥的座右铭送给大家:没有什么使我停留——除了目的,纵然岸旁有玫瑰、有绿荫、有宁静的港湾,我是不系之舟。共勉 💪。